package emergency;

import java.util.ArrayList;

import unit.*;

public abstract class RequirementsEmergency {

	/**
	 * Variable registering the next emergency requirement in the chain of
	 * responsibility
	 */
	private RequirementsEmergency nextInChain;

	/**
	 * Variable registering the total amount of units needed
	 */
	private int totalUnitsNeeded;

	/**
	 * Variable registering the total amount of ambulances needed
	 */
	private int totalAmbulancesNeeded;

	/**
	 * Variable registering the total amount of policecars needed
	 */
	private int totalPoliceCarsNeeded;

	/**
	 * Variable registering the total amount of firetrucks needed
	 */
	private int totalFireTrucksNeeded;

	/**
	 * Method for checking the amount of the given type in the given list
	 * 
	 * @param type
	 *            the type of unit
	 * 
	 * @param list
	 *            the list where to search in
	 * 
	 * @return Returns the amount of units of the given type, in the given list
	 */
	public int amountOfAssignedUnits(String type, ArrayList<Unit> list) {
		int result = 0;
		for (Unit u : list) {
			if (u.getClass().toString().equalsIgnoreCase("class unit." + type))
				result++;
		}
		return result;
	}

	/**
	 * Abstract method for checking the given emergency can be handled by the
	 * concrete emergency requirement
	 * 
	 * @param emergency
	 *            , the emergency you want to check whether it can be handled or
	 *            not
	 * 
	 * @return Returns true when can be handled, false otherwise
	 */
	abstract boolean canHandleEmergency(Emergency emergency);

	/**
	 * Abstract method that will create the suggestion of the given emergency,
	 * with the given units
	 * 
	 * @param emergency
	 *            the given emergency of which the requirements will be
	 *            processed
	 * 
	 * @param units
	 *            list of units that out of which the needed units will be
	 *            picked
	 * 
	 * @return Returns a list of suggested units to assign to the emergency
	 */
	abstract ArrayList<Unit> createSuggestion(Emergency emergency,
			ArrayList<Unit> units);

	/**
	 * Method for computing the difference between 2 integers
	 * 
	 * @param x
	 *            the first integer
	 * 
	 * @param y
	 *            the second integer
	 * 
	 * @return Returns the difference between the two integers
	 */
	protected int diff(int x, int y) {
		return Math.abs(x - y);
	}

	/**
	 * Getter for getting the next emergency requirement in the chain
	 * 
	 * @return Returns the next emergency requirement in the chain
	 */
	public RequirementsEmergency getNextInChain() {
		return nextInChain;
	}

	/**
	 * Getter for getting the total amount of ambulances needed
	 * 
	 * @return Returns the total amount of ambulances needed
	 */
	public int getTotalAmbulancesNeeded() {
		return totalAmbulancesNeeded;
	}

	/**
	 * Getter for getting the total amount of firetrucks needed
	 * 
	 * @return Returns the total amount of firetrucks needed
	 */
	public int getTotalFireTrucksNeeded() {
		return totalFireTrucksNeeded;
	}

	/**
	 * Getter for getting the total amount of ambulances needed
	 * 
	 * @return Returns the total amount of ambulances needed
	 */
	public int getTotalPoliceCarsNeeded() {
		return totalPoliceCarsNeeded;
	}

	/**
	 * Getter for getting the total amount of units needed
	 * 
	 * @return the total amount of units needed
	 */
	public int getTotalUnitsNeeded() {
		return totalUnitsNeeded;
	}

	/**
	 * Setter to set the next emergency requirement in the chain
	 * 
	 * @param nextInChain
	 *            , the next emergency requirement in the chain
	 * 
	 * @post The next requirement in the chain is set
	 */
	public void setNextInChain(RequirementsEmergency nextInChain) {
		this.nextInChain = nextInChain;
	}

	/**
	 * Abstract method for setting the amount of units needed
	 * 
	 * @param emergency
	 *            , the emergency where you want to compute the needing for
	 */
	abstract void setRequirements(Emergency emergency);

	/**
	 * Setter for setting the total amount of ambulances needed
	 * 
	 * @param totalAmbulancesNeeded
	 *            The total amount of ambulances needed
	 * 
	 * @post The total amount of ambulances needed is set to the given amount
	 */
	protected void setTotalAmbulancesNeeded(int totalAmbulancesNeeded) {
		this.totalAmbulancesNeeded = totalAmbulancesNeeded;
	}

	/**
	 * Setter for setting the total amount of firetrucks needed
	 * 
	 * @param totalFireTrucksNeeded
	 *            The total amount of firetrucks needed
	 * 
	 * @post The total amount of firetrucks needed is set to the given amount
	 */
	protected void setTotalFireTrucksNeeded(int totalFireTrucksNeeded) {
		this.totalFireTrucksNeeded = totalFireTrucksNeeded;
	}

	/**
	 * Setter for setting the total amount of policecars needed
	 * 
	 * @param totalPoliceCarsNeeded
	 *            The total amount of policecars needed
	 * 
	 * @post The total amount of policecars needed is set to the given amount
	 */
	protected void setTotalPoliceCarsNeeded(int totalPoliceCarsNeeded) {
		this.totalPoliceCarsNeeded = totalPoliceCarsNeeded;
	}

	/**
	 * Setter for setting the total amount of units needed
	 * 
	 * @param totalUnitsNeeded
	 *            The total amount of units needed
	 * 
	 * @post The total amount of units needed is set to the given amount
	 */
	protected void setTotalUnitsNeeded(int totalUnitsNeeded) {
		this.totalUnitsNeeded = totalUnitsNeeded;
	}

	/**
	 * Method for checking the given unit is needed in this requirement
	 * 
	 * @param u
	 *            the unit you want to check that is needed
	 * 
	 * @return Returns true if the given unit is needed, false if not
	 */
	boolean unitNeeded(Unit u) {
		if (u instanceof FireTruck && getTotalFireTrucksNeeded() > 0)
			return true;

		if (u instanceof Ambulance && getTotalAmbulancesNeeded() > 0)
			return true;

		if (u instanceof PoliceCar && getTotalPoliceCarsNeeded() > 0)
			return true;

		return false;
	}

}
